#ifndef __BASIC_MISC_H__
#define __BASIC_MISC_H__

#if defined(__linux__)
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#endif

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <time.h>
#include <math.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdarg.h>
#include <pthread.h>
#include <signal.h>
#include <semaphore.h>
#include <mqueue.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/mman.h>
#include <sys/sem.h>
#include <sys/resource.h>
#include <dirent.h>
#include <getopt.h>
#include <regex.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <sys/select.h>
#include <sys/poll.h>
#include <netdb.h>
#include <pwd.h>

#if defined(__APPLE__) || defined(__FreeBSD__)
#include <machine/endian.h>
#else
#include <endian.h>
#endif

__BEGIN_DECLS

/*======*/
/* 常量 */
/*======*/
#define ZERO                    '\0'        /* 数值0 */
#define ZEROS                   ""          /* 空字串 */
#define CHAR0                   '0'         /* 字符'0' */
#define RTN                     '\n'        /* 回车 */
#define RTNS                    "\n"        /* 回车字串 */
#define CRLF                    "\r\n"      /* 换行符 */
#define SLASH                   '/'         /* 斜杠 */
#define BACKSLASH               '\\'        /* 反斜杠 */
#define TAB                     '\t'        /* TAB */
#define TABS                    "\t"        /* TAB串 */
#define SPACE                   ' '         /* 空格 */
#define SPACES                  " "         /* 字符串空格*/
#define OPTION_FMT              "%1d"       /* 选项格式 */
#define SHORT_NUMBER_FMT        "%06d"      /* 短整数格式 */
#define LONG_NUMBER_FMT         "%012ld"    /* 长整数格式 */
#define LLONG_NUMBER_FMT        "%012lld"   /* 超长整数格式 */
#define IS_TRUE                 1           /* 为真 */
#define IS_FALSE                0           /* 为假 */

#define BIT_OF_BYTE		8			        /* 字节位数 */
#define BIT_OF_CHAR		BIT_OF_BYTE         /* char位数 */
#define BIT_OF_INT      (sizeof(int)*BIT_OF_CHAR)   /* int位数 */
#define KB(n)           ((n)*1024)	        /* n KB */
#define MB(n)           ((n)*KB(1024))	    /* n MB */
#define GB(n)           ((n)*MB(1024))	    /* n GB */
#define MSG_SIZE_SIZE		 	6			/* 消息大小的大小 */
#define MSG_SIZE			 	KB(1024)	/* 消息大小 */
#define BUFFER_SIZE			 	KB(1)		/* 缓冲区大小 */
#define FILE_NM_SIZE		 	80			/* 文件名大小 */
#define LONG_FILE_NM_SIZE	 	200			/* 完整文件名大小 */
#define IP_SIZE					15			/* IP地址大小 */
#define OPTION_SIZE				1			/* 选项大小 */
#define SHORT_NUMBER_SIZE		6			/* 短整数大小 */
#define LONG_NUMBER_SIZE		12			/* 长整数大小 */
#define LLONG_NUMBER_SIZE		12			/* 超长整数大小 */
#define NAME_SIZE				30			/* 名称大小 */
#define LONG_NAME_SIZE          200         /* 长名称大小 */
#define PASSWD_MIN_SIZE			6			/* 最短口令 */
#define PASSWD_MAX_SIZE			15			/* 最长口令 */
#define PASSWD_ENC_SIZE         32          /* 加密后口令大小 */

/*======*/
/* 标志 */
/*======*/
#define FLAG_MULTI_THREAD       0x80000000  /* 多线程 */
#define FLAG_LOCAL              0x40000000  /* 本地 */
#define FLAG_CASE_SENSITIVE     0x20000000  /* 大小写敏感 */

/*----- 字符操作 -----*/
#define CLR_BUF(_buf) (_buf)[0]=ZERO
#define BUF_IS_CLR(_buf) ((_buf)[0]==ZERO)

/*
 * 16进制数转换成字符
 * 返回：
 */
extern char *	/* 参数str:成功 NULL:长度小于等于0 */
expand_to_str(
        unsigned char *hex,	/* [IN] 16进制数 */
        int size,			/* [IN] 16进制数长度 */
        char *str			/* [OUT] 字符 */
        );

/*
 * 字符换成16进制数
 */
extern unsigned char *	/* 参数hex:成功 NULL:长度小于等于0或不是2的倍数 */
collapse_from_str(
        char *str,			/* [IN] 字符 */
        int size,			/* [IN] 字符长度 */
        unsigned char *hex  /* [OUT] 16进制数 */
        );

/*
 * 截去字符串头部空格
 */
extern char *	/* 参数str */
trim_head_space(
        char *str			/* [IN,OUT] 字符串 */
        );

/*
 * 截去字符串尾部空格
 */
extern char *	/* 参数str */
trim_tail_space(
        char *str			/* [IN,OUT] 字符串 */
        );

/*
 * 截去字符串尾部空格，如全部为空格，则留一个空格
 */
extern char *	/* 参数str */
trim_tail_space_notnull(
        char *str			/* [IN,OUT] 字符串 */
        );

/*
 * 截去多余空格 
 */
extern char *	/* 参数str */
trim_redundant_space(
        char *str			/* [IN,OUT] 字符串 */
        );

/*
 * 截去字符串首尾空格
 */
extern char *	/* 参数str */
trim_space(
        char *str			/* [IN,OUT] 字符串 */
        );

/*
 * 以空格补足字符串
 */
extern char *	/* 参数str:成功 NULL:缓冲区大小<=0 */
pad_space(
        char *str,			/* [IN,OUT] 字符串 */
        int buflen			/* [IN] 字符串缓冲区大小 */
        );

/*
 * 将tab扩展成空格
 */
extern char *	/* 参数str:成功 NULL:缓冲区大小不够 */
expand_tab(
        char *str,			/* [IN,OUT] 字符串 */
        int buflen,         /* [IN] 字符串缓冲区大小 <=0:不考虑大小 */
        int unit            /* [IN] 扩展单位 <=0:缺省4空格 */
        );

/*
 * 计算数据HASH值
 */
extern unsigned int /* HASH值(正整数):成功 0:字符串无效或长度小于等于0 */
get_hash(
    unsigned char *data,    /* [IN] 字符串 */
    int len                 /* [IN] 计算HASH的字符串长度 */
);

/*
 * 包装消息长度
 */
extern int	/* 0:成功 -1:参数无效 */
wrap_size(
        unsigned char *msg_in,		/* [IN] 输入消息 */
        int *msg_size,		        /* [IN] 输入消息长度 [OUT] 输出消息长度 */
        unsigned char *msg_out		/* [OUT] 输出消息，可与msg_in相同 */
        ); 

/*
 * 去除消息长度
 */
extern int	/* 0:成功 -1:参数无效 */
unwrap_size(
        unsigned char *msg_in,		/* [IN] 输入消息 */
        int *msg_size,		        /* [IN] 输入消息长度 [OUT] 输出消息长度 */
        unsigned char *msg_out		/* [OUT] 输出消息，可与msg_in相同 */
        );

/*
 * 分解字符串
 */
extern int  /* >0:分解项数量 <=0:未能解析 */
str_split(
        char *str,          /* [IN] 输入字符串 */
        char delim,         /* [IN] 分隔符，0:以空格和tab为分隔符 */
        char ***arrp        /* [OUT] 项目数组 用FREE_PTR_ARRAY释放 */
        );

/*
 * 转换字符串中字母为大写
 */
extern char	*   /* 参数str */
str_toupper(
        char *str			/* [IN,OUT] 字符串 */
        );

/*
 * 转换字符串中字母为小写
 */
extern char	*   /* 参数str */
str_tolower(
        char *str			/* [IN,OUT] 字符串 */
        );

/*
 * 替换字符串
 */
extern char *   /* 目标字符串，即参数dest */
str_replace(
        char *src,          /* [IN] 源字符串 */
        char *old,          /* [IN] 被替换字符串 */
        char *rep,          /* [IN] 替换字符串 */
        char *dest          /* [OUT] 目标字符串，应用需保证不越界，NULL表示分配新字符串，勿忘释放 */
        );

/*
 * 插入字符串
 */
extern char *   /* 源字符串，即参数str */
str_insert(
        char *str,          /* [IN,OUT] 源字符串 */
        int start,          /* [IN] 起始位置 */
        char *ins           /* [IN] 插入字符串 */
        );

/*
 * 判断字符串是否由10进制字符组成
 */
extern int  /* 1:是 0:否 */
str_is_dec(
        char *str           /* [IN] 字符串 */
        );

/*
 * 判断字符串是否由16进制字符组成
 */
extern int  /* 1:是 0:否 */
str_is_hex(
        char *str           /* [IN] 字符串 */
        );

/*
 * 按字面将10进制数转变为16进制数
 */
extern int  /* 16进制数 */
dec_to_hex(
        int dec             /* [IN] 10进制数 */
        );

/*
 * 补齐大小
 */
extern int  /* 补齐后大小 */
pack_size(
        int org_size,       /* [IN] 原大小 */
        int unit            /* [IN] 补齐单位 */
        );

/*----- 校验 -----*/
/*
 * CRC短整型值
 */
extern unsigned short	/* 0:成功 -1:参数无效 */
get_crc_16(
        unsigned char *p,   /* [IN] 输入缓冲区 */
        int count			/* [IN] 校验长度 */
        );

/*----- 内存操作 -----*/
#define ALLOC_MULTI(_ptr,_type,_num,_errlabel)                  \
do                                                              \
{                                                               \
    if(((_ptr)=(_type *)malloc(sizeof(_type)*(_num))) == NULL)  \
    {                                                           \
        goto _errlabel;                                         \
    }                                                           \
} while(0)

#define ALLOC(_ptr,_type,_errlabel)							    \
ALLOC_MULTI(_ptr,_type,1,_errlabel)

#define ALLOC_ARRAY(_ptr,_type,_num,_size,_errlabel)            \
do                                                              \
{                                                               \
	int _inc;												    \
															    \
	_inc=(_num);										        \
	ALLOC_MULTI(_ptr,_type,_inc,_errlabel);					    \
	_size=_inc;												    \
} while(0)

#define EXPAND_ARRAY(_ptr,_type,_num,_size,_errlabel)		    \
do                                                              \
{                                                               \
	int _inc;												    \
    _type *_ptr_tmp;                                            \
															    \
	_inc=(_num);											    \
    if((_ptr_tmp=(_type *)realloc((_ptr),                       \
        sizeof(_type)*((_size)+(_inc)))) == NULL)			    \
    {                                                           \
        goto _errlabel;                                         \
    }                                                           \
    _size+=_inc;                                 			    \
    _ptr=_ptr_tmp;                                              \
} while(0)

#define ALLOC_MULTI_RETERR(_ptr,_type,_num,_errcode)            \
do                                                              \
{                                                               \
    if(((_ptr)=(_type *)malloc(sizeof(_type)*(_num))) == NULL)  \
    {                                                           \
        return(_errcode);                                       \
    }                                                           \
} while(0)

#define ALLOC_RETERR(_ptr,_type,_errcode)					    \
ALLOC_MULTI_RETERR(_ptr,_type,1,_errcode)

#define ALLOC_ARRAY_RETERR(_ptr,_type,_num,_size,_errcode)      \
do                                                              \
{                                                               \
	int _inc;												    \
															    \
	_inc=(_num);											    \
	ALLOC_MULTI_RETERR(_ptr,_type,_inc,_errcode);			    \
	_size=_inc;												    \
} while(0)

#define EXPAND_ARRAY_RETERR(_ptr,_type,_num,_size,_errcode)	    \
do                                                              \
{                                                               \
	int _inc;												    \
    _type *_ptr_tmp;                                            \
															    \
	_inc=(_num);											    \
    if((_ptr_tmp=(_type *)realloc((_ptr),                       \
        sizeof(_type)*((_size)+(_inc)))) == NULL)			    \
    {                                                           \
        return(_errcode);                                       \
    }                                                           \
    _size+=_inc;                                 			    \
    _ptr=_ptr_tmp;                                              \
} while(0)

#define ALLOC_MULTI_DOERR(_ptr,_type,_num,_doerr)               \
do                                                              \
{                                                               \
    if(((_ptr)=(_type *)malloc(sizeof(_type)*(_num))) == NULL)  \
    {                                                           \
        _doerr;                                                 \
    }                                                           \
} while(0)

#define ALLOC_DOERR(_ptr,_type,_doerr)                          \
ALLOC_MULTI_DOERR(_ptr,_type,1,_doerr)

#define ALLOC_ARRAY_DOERR(_ptr,_type,_num,_size,_doerr)         \
do                                                              \
{                                                               \
	int _inc;												    \
															    \
	_inc=(_num);											    \
	ALLOC_MULTI_DOERR(_ptr,_type,_inc,_doerr);		            \
	_size=_inc;												    \
} while(0)

#define EXPAND_ARRAY_DOERR(_ptr,_type,_num,_size,_doerr)	    \
do                                                              \
{                                                               \
	int _inc;												    \
    _type *_ptr_tmp;                                            \
															    \
	_inc=(_num);											    \
    if((_ptr_tmp=(_type *)realloc((_ptr),                       \
        sizeof(_type)*((_size)+(_inc)))) == NULL)			    \
    {                                                           \
        _doerr;                                                 \
    }                                                           \
    _size+=_inc;                                 			    \
    _ptr=_ptr_tmp;                                              \
} while(0)

#define FREE(_ptr)                                              \
do                                                              \
{                                                               \
    if(_ptr)  free(_ptr);                                       \
    _ptr=NULL;                                                  \
} while(0)

#define FREE_PTR_ARRAY(_array, _size)                           \
do                                                              \
{                                                               \
    if(_array)                                                  \
    {                                                           \
        int _i;                                                 \
        for(_i=0; _i<_size; _i++)                               \
        {   if(_array[_i]) free(_array[_i]);   }                \
        free(_array); _array=NULL;                              \
    }                                                           \
} while(0)

#define CLR_PTR_ARRAY(_array, _size)                            \
do                                                              \
{                                                               \
    if(_array)                                                  \
    {                                                           \
        int _i;                                                 \
        for(_i=0; _i<_size; _i++)                               \
            (_array[_i])=NULL;                                  \
    }                                                           \
} while(0)


/*----- 随机数 -----*/
/*
 * 生成整型随机数
 */
extern int	/* 整型随机数 */
random_int(
        int min_val,		/* [IN] 最小值 */
        int max_val,		/* [IN] 最大值 */
        unsigned int *seedp /* [IN,OUT] 种子 */
        );

/*
 * 随机排列整型数组
 */
extern int
random_array_int(
        int array[],        /* [IN,OUT] 整型数组 */
        int num             /* [IN] 数组大小 */
        );

/*
 * 随机口令
 */
extern char *   /* 口令，即参数password */
random_password(
        char *password,     /* [IN,OUT] 口令 */
        int size            /* [IN] 口令长度 */
        );

/*----- 文件目录操作 -----*/
/*
 * 提取目录名
 */
extern char *   /* 目录名，即参数dirname */
extract_dirname(
        char *filename,     /* [IN] 完整文件名 */
        char *dirname       /* [OUT] 目录名 */
        );

/*
 * 提取文件名
 */
extern char *   /* 文件名，即参数basename */
extract_basename(
        char *filename,     /* [IN] 完整文件名 */
        char *basename      /* [OUT] 文件名 */
        );

/*
 * 删除目录
 */
extern int  /* 0:成功 -1:获取文件或目录属性出错 -2:删除目录出错 -3:删除文件出错 */
remove_dir(
        char *path          /* [IN] 目录 */
        );

/*
 * 创建目录
 */
extern int  /* 0:成功 -1:获取文件或目录属性出错 -2:目录属性错误 -3:mkdir出错 */
create_dir(
        char *dir           /* [IN] 目录 */
        );

/*----- 其它 -----*/
#define DEEP_SLEEP	select(0, NULL, NULL, NULL, NULL)

__END_DECLS

#endif
